/*
 * Copyright (c) 2015 www.smarthome.com All rights reserved. 本软件源代码版权归----所有,未经许可不得任意复制与传播.
 */
package com.smarthome.common.tools.date;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import org.apache.commons.lang.StringUtils;

/**
 * 日期工具类.
 * 
 * @author KongXiangyu
 * @since 2015-05-15
 */
public class DateUtils {

    /**
     * Gets the server time.
     * 
     * @return the server time
     */
    public static long getServerTime() {
        return System.currentTimeMillis();
    }

    /**
     * 格式化日期,默认返回yyyy-MM-dd HH:mm:ss.
     * 
     * @param date the date
     * @return the string
     */
    public static String format(Date date) {
        return format(date, DateFormat.YYYY_MM_DD_HH_mm_ss);
    }

    /**
     * 格式化显示当前日期.
     * 
     * @param format the format
     * @return the string
     */
    public static String format(String format) {
        return format(new Date(), format);
    }

    /**
     * 日期格式化.
     * 
     * @param date the date
     * @param format the format
     * @return the string
     */
    public static String format(Date date, String format) {
        if (date == null)
            return null;
        try {
            SimpleDateFormat sdf = new SimpleDateFormat(format);
            return sdf.format(date);
        } catch (Exception e) {
            throw new RuntimeException("日期格式化转换失败", e);
        }
    }

    /**
     * 时间格式化， 传入毫秒.
     * 
     * @param time the time
     * @return the string
     */
    public static String dateFormat(long time) {
        return format(new Date(time), DateFormat.YYYY_MM_DD_HH_mm_ss);
    }

    /**
     * 日期字符串从旧格式转换为新格式.
     * 
     * @param dateStr the date str
     * @param oldFromat the old fromat
     * @param newFormat the new format
     * @return the string
     */
    public static String format(String dateStr, String oldFromat, String newFormat) {
        try {
            if (StringUtils.isBlank(dateStr)) {
                return null;
            }

            SimpleDateFormat sdf1 = new SimpleDateFormat(oldFromat);
            Date date = sdf1.parse(dateStr);

            return format(date, newFormat);

        } catch (Exception e) {
            throw new RuntimeException("日期格式化转换失败", e);
        }
    }

    /**
     * 日期字符串转换为Calendar对象.
     * 
     * @param dateStr the date str
     * @param dateStrFormat the date str format
     * @return the calendar
     */
    public static Calendar format(String dateStr, String dateStrFormat) {
        try {
            if (StringUtils.isBlank(dateStr)) {
                return null;
            }
            SimpleDateFormat sdf = new SimpleDateFormat(dateStrFormat);
            Date date = sdf.parse(dateStr);
            Calendar ca = GregorianCalendar.getInstance();
            ca.setTime(date);
            return ca;
        } catch (Exception e) {
            throw new RuntimeException("日期格式化转换失败", e);
        }
    }

    /**
     * 日期字符串转换为Date对象.
     * 
     * @param dateStr the date str
     * @param dateStrFormat the date str format
     * @return the date
     */
    public static Date dateStr2Date(String dateStr, String dateStrFormat) {
        try {
            if (StringUtils.isBlank(dateStr)) {
                return null;
            }
            SimpleDateFormat sdf = new SimpleDateFormat(dateStrFormat);
            return sdf.parse(dateStr);
        } catch (Exception e) {
            throw new RuntimeException("日期格式化转换失败", e);
        }
    }

    /**
     * 增加日期的天数：Calendar.DAY_OF_MONTH
     * 
     * @param date the date
     * @param amount the amount
     * @return the date
     * @createTime 2015-5-22 下午11:49:56
     */
    public static Date addDays(Date date, int amount) {
        return add(date, Calendar.DAY_OF_MONTH, amount);
    }

    /**
     * Adds the hours: Calendar.HOUR_OF_DAY
     * 
     * @param date the date
     * @param amount the amount
     * @return the date
     */
    public static Date addHours(Date date, int amount) {
        return add(date, Calendar.HOUR_OF_DAY, amount);
    }

    /**
     * Adds the seconds：Calendar.SECOND
     * 
     * @param date the date
     * @param amount the amount
     * @return the date
     */
    public static Date addSeconds(Date date, int amount) {
        return add(date, Calendar.SECOND, amount);
    }

    public static Date addMilliSeconds(Date date, int amount) {
        return add(date, Calendar.MILLISECOND, amount);
    }

    /**
     * current date Adds the seconds：Calendar.SECOND
     * 
     * @param date the date
     * @param amount the amount
     * @return the date
     */
    public static Date addSeconds(int amount) {
        return add(new Date(), Calendar.SECOND, amount);
    }

    /**
     * Adds the field
     * 
     * @param date the date
     * @param field the field
     * @param amount the amount
     * @return the date
     */
    private static Date add(Date date, int field, int amount) {

        if (null == date) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(field, amount);
        return cal.getTime();

    }

    /**
     * 格式化日期字符串为日期时间字符串，以0点0时0分开始。例如：2012-04-14 格式化为2012-04-14 00:00:00
     * 
     * @param dateStr the date str
     * @return the string
     */
    public static String formatDate2DateTimeStart(String dateStr) {
        Calendar calendar = DateUtils.format(dateStr, DateFormat.YYYY_MM_DD);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return format(calendar.getTime());
    }

    /**
     * 格式化日期字符串为日期时间字符串，以23点59时59分结束。例如：2012-04-14 格式化为2012-04-14 23:59:59
     * 
     * @param dateStr the date str
     * @return the string
     */
    public static String formatDate2DateTimeEnd(String dateStr) {
        Calendar calendar = DateUtils.format(dateStr, DateFormat.YYYY_MM_DD);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return format(calendar.getTime());
    }

    /**
     * 格式化日期字符串为日期时间字符串，以0点0时0分开始。例如：2012-04-14 格式化为2012-04-14 00:00:00
     * 
     * @param dateStr the date str
     * @return the string
     */
    public static Date formatDate2DateTimeStart(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    /**
     * 格式化日期字符串为日期时间字符串，以23点59时59分结束。例如：2012-04-14 格式化为2012-04-14 23:59:59
     * 
     * @param dateStr the date str
     * @return the string
     */
    public static Date formatDate2DateTimeEnd(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return calendar.getTime();
    }

    /**
     * 日期格式化 返回格式 yyyy-MM-dd HH:mm:ss
     * @param date
     * @return
     */
    public static Date formatDateStr2Date(String date) {
        return DateUtils.dateStr2Date(date, DateFormat.YYYY_MM_DD_HH_mm_ss);
    }

    public static Date getCurrentDate() {
        return new Date();
    }

    public static Date addMinutes(Date nextDate, int amount) {
        return add(new Date(), Calendar.MINUTE, amount);
    }

    /**
     * 获取endDate与startDate日期相隔天数
     * 
     * @param endDate
     * @param startDate
     * @return
     * @author Gavin
     */
    public static Long getDays(Date endDate, Date startDate) {
        if (endDate == null || startDate == null) {
            return null;
        }
        return (endDate.getTime() - startDate.getTime()) / (24 * 60 * 60 * 1000);
    }

    /**
     * 获取endDate与startDate日期相隔天数余下的小时数
     * 
     * @param endDate
     * @param startDate
     * @return
     */
    public static Long getDaysRemainingHours(Date endDate, Date startDate) {
        if (endDate == null || startDate == null) {
            return null;
        }
        return ((endDate.getTime() - startDate.getTime()) % (24 * 60 * 60 * 1000)) / (60 * 60 * 1000);
    }

    /**
     * 获取endDate与startDate日期相隔小时数
     * 
     * @param endDate
     * @param startDate
     * @return
     * @author Gavin
     */
    public static Long getHours(Date endDate, Date startDate) {
        if (endDate == null || startDate == null) {
            return null;
        }
        return (endDate.getTime() - startDate.getTime()) / (60 * 60 * 1000);
    }

    /**
     * 获取endDate与startDate日期相隔小时数余下的分钟数
     * 
     * @param endDate
     * @param startDate
     * @return
     * @author Gavin
     */
    public static Long getHoursRemainingMints(Date endDate, Date startDate) {
        if (endDate == null || startDate == null) {
            return null;
        }
        return ((endDate.getTime() - startDate.getTime()) % (60 * 60 * 1000)) / (60 * 1000);
    }

    /**
     * 获取endDate与startDate日期相隔分钟数
     * 
     * @param endDate
     * @param startDate
     * @return
     */
    public static Long getMinutes(Date endDate, Date startDate) {
        if (endDate == null || startDate == null) {
            return null;
        }
        return (endDate.getTime() - startDate.getTime()) / (60 * 1000);
    }

    /**
     * 获取endDate与startDate日期相隔秒数
     * 
     * @param endDate
     * @param startDate
     * @return
     */
    public static Long getSeconds(Date endDate, Date startDate) {
        if (endDate == null || startDate == null) {
            return null;
        }
        return (endDate.getTime() - startDate.getTime()) / 1000;
    }

    /**
     * 判断两个时间是否是同一日期。
     * 
     * @param date1
     * @param date2
     * @return
     */
    public static boolean isTheSameDay(Date date1, Date date2) {
        if (date1 == date2) {
            return true;
        } else if (date1 == null || date2 == null) {
            return false;
        }
        final Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);
        final Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        return isTheSameDay(cal1, cal2);
    }

    /**
     * 判断两个日历是否是同一日期。
     * 
     * @param cal1
     * @param cal2
     * @return
     */
    public static boolean isTheSameDay(Calendar cal1, Calendar cal2) {
        if (cal1 == cal2) {
            return true;
        } else if (cal1 == null || cal2 == null) {
            return false;
        }
        return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA)) && (cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR)) && (cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
    }

    public static Date getTodayMinTime() {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 1);
        return c.getTime();
    }

    public static Date getTodayMaxTime() {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.HOUR_OF_DAY, 23);
        c.set(Calendar.MINUTE, 59);
        c.set(Calendar.SECOND, 59);
        return c.getTime();
    }

    /**
     * 比较时间1和时间2 是否一致，精确到秒
     * @param time1
     * @param time2
     * @return
     */
    public static boolean equals(Date time1, Date time2) {
        /**
         * 比较方式 1 直接比较数值 xxxxxL==xxxx.getDate().getTime() 2 比较毫秒数time1.compareTo(time2)==0 皆有误差,导致判断不准，如下面的例子，都会打印出false System.out.println(DateUtils.format(new Date(1431085157467L)));
         *
         * Calendar carender=GregorianCalendar.getInstance(); carender.set(2015, 5, 8, 19, 39, 17); System.out.println(DateUtils.format(carender.getTime()));
         *
         * System.out.println(1431085157467L==carender.getTime().getTime()); System.out.println(new Date(1431085157467L).compareTo(carender.getTime())==0);
         * 
         */

        // 在有误差的情况下，换算成字符串，精确到秒
        if ((time1 == null && time2 != null) || (time1 != null && time2 == null)) {
            return false;
        }
        if (time1 == null && time2 == null) {
            return true;
        }
        return StringUtils.equals(DateUtils.format(time1), DateUtils.format(time2));
    }
}
